using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//记录背包关联的数据
public class BagModel
{
  protected class Entry
  {
    public int id;
    public int curCount;
    public int maxCount;

    public EntryInfo ToInfo() {
      return EntryInfo.Create(id, curCount, maxCount);
    }
  }

  public struct EntryInfo
  {
    public int id {
      get {
        if (!m_valid)
        {
          Debug.LogError("acess invalid entry");
        }
        return m_key;
      }
    }
    public int curCount {
      get {
        if (!m_valid)
        {
          Debug.LogError("acess invalid entry");
        }
        return m_curCount;
      }
    }
    public int maxCount {
      get {
        if (!m_valid)
        {
          Debug.LogError("access invalid entry");
        }
        return m_maxCount;
      }
    }

    private int m_key;
    private int m_curCount;
    private int m_maxCount;

    private bool m_valid;

    public bool isValid => m_valid;

    public static EntryInfo INVALID => new EntryInfo {
      m_valid = false
    };

    public static EntryInfo Create(int id, int curCount, int maxCount) {
      var info = new EntryInfo();
      info.m_valid = true;
      info.m_maxCount = maxCount;
      info.m_curCount = curCount;
      info.m_key = id;
      return info;
    }
  }

  private Dictionary<int, Entry> m_entryDict = new Dictionary<int, Entry>();

  public void RegisterEntry(int id) {
    if (!m_entryDict.ContainsKey(id))
    {
      m_entryDict[id] = new Entry() {
        id = id
      };
    }
  }

  public EntryInfo GetEntryInfo(int id) {
    if (m_entryDict.ContainsKey(id))
    {
      return m_entryDict[id].ToInfo();
    }
    return EntryInfo.INVALID;
  }

  public IEnumerable<EntryInfo> GetAllEntrys() {
    foreach (var entry in m_entryDict.Values)
    {
      yield return entry.ToInfo();
    }
  }

  public void ResetToMax(int id) {
    if (!m_entryDict.ContainsKey(id))
    {
      Debug.LogError("[ResetToMax] id no exist: " + id);
      return;
    }
    var entry = m_entryDict[id];
    entry.curCount = entry.maxCount;
  }

  public void UpdateEntryMax(int id, int maxCount) {
    if (!m_entryDict.ContainsKey(id))
    {
      Debug.LogError("[UpdateEntryMax] id no exist: " + id);
      return;
    }
    var entry = m_entryDict[id];
    maxCount = Mathf.Max(0, maxCount);
    entry.maxCount = maxCount;
  }

  public void UpdateEntryCurrent(int id, int curCount) {
    if (!m_entryDict.ContainsKey(id))
    {
      Debug.LogError("[UpdateEntryCurrent] id no exist: " + id);
      return;
    }
    var entry = m_entryDict[id];
    curCount = Mathf.Clamp(curCount, 0, entry.maxCount);
    entry.curCount = curCount;
  }

  public void UpdateEntry(int id, int curCount, int maxCount) {
    if (!m_entryDict.ContainsKey(id))
    {
      Debug.LogError("[UpdateEntry] id no exist: " + id);
      return;
    }
    var entry = m_entryDict[id];
    maxCount = Mathf.Max(0, maxCount);
    curCount = Mathf.Clamp(curCount, 0, maxCount);
    entry.curCount = curCount;
    entry.maxCount = maxCount;
  }


  public bool IsEmpty() {
    foreach (var ball in m_entryDict.Values)
    {
      if (ball.curCount > 0)
      {
        return true;
      }
    }
    return false;
  }

  /// <summary>
  /// 尝试扣除指定的球
  /// </summary>
  /// <param name="count">希望扣除的数量</param>
  /// <returns>未能成功扣除的数量，0等于正好扣除，大于0则有不足以扣除的情况，-1为不存在该球</returns>
  public int TryConsume(int id, int count) {
    if (m_entryDict.ContainsKey(id))
    {
      if (m_entryDict[id].curCount >= count)
      {
        m_entryDict[id].curCount -= count;
        return 0;
      } else
      {
        var cur = m_entryDict[id].curCount;
        m_entryDict[id].curCount = 0;
        return count - cur;
      }
    }
    return -1;
  }

  public EntryInfo GetNotEmptyEntryRandomly() {
    var notEmptyList = new List<Entry>();
    foreach (var entry in m_entryDict.Values)
    {
      if (entry.curCount > 0)
      {
        notEmptyList.Add(entry);
      }
    }
    if (notEmptyList.Count > 0)
    {
      return notEmptyList[Random.Range(0, notEmptyList.Count)].ToInfo();
    } else
    {
      //没有球的时候返回null
      return EntryInfo.INVALID;
    }
  }
  public void ReloadBag() {
    foreach (var entry in GetAllEntrys())
    {
      ResetToMax(entry.id);
    }
  }
}
